/**
 * 使用XMLHttpRequest进行单个文件上传的实现
 * 用法
 * import upload from 'libs/upload_xhr';
 * upload(opts);
 * opts.url String 上传地址
 * opts.headers Object 上传的请求头部，视需要配置
 * opts.data Object 上传配置参数，依据dataFormat而不同
 * opts.dataFormat String 上传表单类型，有formData和base64两种
 * opts.timeout Number 上传超时时间，0表示永不超时
 * opts.beforeUpload Fuunction 开始上传前的回调函数
 * opts.onUploading Function (progress) ajax上传过程中的回调函数
 * opts.onSuccess Function (data) 上传成功时的回调函数
 * opts.onError Function (type, msg) 上传失败时的回调函数{0:放弃,1:超时,2:故障,3:其他}
 */

export default function (opts) {
  let defs = {
    url: "", // 上传地址
    headers: {}, // 上传的请求头部，视需要配置
    data: {}, // 上传配置参数，依据dataFormat而不同，
    dataFormat: 'formData', // 上传表单类型，有formData和base64两种
    timeout: 0, // 上传超时时间，0表示永不超时
    beforeUpload: function () { // ajax上传前的回调函数
      console.log('开始上传');
      console.log(this);
    },
    onUploading: function (progress) { // ajax上传过程中的回调函数
      console.log('当前进度：' + progress + '%');
    },
    onSuccess: function (d) { // 上传成功时的回调函数
      console.log('上传完成', d);
    },
    onError: function (type, msg) { // 上传失败时的回调函数{0:放弃,1:超时,2:故障,3:其他}
      console.log('错误' + type + '：' + msg);
    },
  };
  opts = { ...defs, ...opts };

  let xhr = new XMLHttpRequest();
  xhr.open("POST", opts.url);
  Object.keys(opts.headers).forEach(key => {
    xhr.setRequestHeader(key, opts.headers[key]);
  });
  xhr.timeout = opts.timeout;
  xhr.addEventListener("load", function (e) {
    if (this.status == 200) {
      opts.onSuccess(this.response);
    } else {
      opts.onError(3, '其他原因');
    }
  });
  xhr.addEventListener("error", function () {
    opts.onError(2, '网络故障');
  });
  xhr.addEventListener("timeout", function () {
    opts.onError(1, '上传超时');
  });
  xhr.addEventListener("abort", function () {
    opts.onError(0, '取消上传');
  });
  xhr.upload.addEventListener('progress', function (e) {
    if (xhr.status == 200) {
      if (e.lengthComputable) {
        opts.onUploading(Math.floor(e.loaded / e.total * 100));
      }
    }
  });

  opts.beforeUpload();
  switch (opts.dataFormat) {
    case 'formData':
      let fd = new FormData();
      Object.keys(opts.data).forEach(key => {
        fd.append(key, opts.data[key]);
      });
      xhr.send(fd);
      return xhr;
    case 'base64':
      xhr.setRequestHeader('Content-Type', 'application/json');
      xhr.send(JSON.stringify(opts.data));
      return xhr;
  }
};
